﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace WJP.ComponentModel
{
    /// <summary>
    /// 用于存储插件所需的所有信息
    /// </summary>
    public class PluginInfo
    {
        /// <summary>
        /// 程序集当中的插件对象。
        /// <para>如果插件中没有定义，则此属性为 null。</para>
        /// </summary>
        public PluginBase Instance { get; private set; }

        /// <summary>
        /// 程序集本身
        /// </summary>
        public Assembly Assembly { get; private set; }

        /// <summary>
        /// 插件的类型
        /// </summary>
        public Type Type { get; }

        /// <summary>
        /// 此插件的所有依赖插件
        /// </summary>
        public List<PluginInfo> Dependencies { get; }

        /// <summary>
        /// 本属性表示插件在所有插件中的启动索引号。
        /// <para></para>索引号表示了插件的启动优先级，索引号越小，越先被启动。
        /// <para></para>该优先级的计算方式为：
        /// <para></para>1. 所有 DomainPlugin 的索引号应小于所有的 UIPlugin 的索引号；
        /// <para></para>2. 接着按照 SetupLevel 进行排序，越小的 SetupLevel 对应越小的索引号。
        /// <para></para>3. 对于 SetupLevel 相同的插件，则根据引用关系对插件进行排序，引用其它插件越少的插件，对应的索引号更小。
        /// </summary>
        public int SetupIndex { get; internal set; }

        /// <summary>
        /// 表示某一个插件程序集
        /// </summary>
        /// <param name="assembly">程序集</param>
        /// <param name="instance">插件</param>
        /// <param name="type">插件的类型</param>
        public PluginInfo(Assembly assembly, PluginBase instance, Type type)
        {
            Check.NotNull(assembly, nameof(assembly));
            Check.NotNull(instance, nameof(instance));
            Check.NotNull(type, nameof(type));

            this.Instance = instance;
            this.Assembly = assembly;
            this.Type = type;

            Dependencies = new List<PluginInfo>();
        }

        public override string ToString()
        {
            return Assembly.FullName;
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            if (obj.GetType().Equals(this.GetType()) == false)
                return false;
            var pluginInfo = obj as PluginInfo;
            return this.Instance == pluginInfo.Instance && this.Assembly == pluginInfo.Assembly;
        }

        public override int GetHashCode()
        {
            return this.Instance.GetHashCode() + this.Assembly.GetHashCode();
        }
    }
}
